package com.cloud.rou.im.cluster.loadbalance;

import com.cloud.rou.im.cluster.naming.node.ImServerInstance;
import com.cloud.rou.im.cluster.zk.ZookeeperClientFactory;
import com.cloud.rou.im.protocol.serialize.FastJsonSerializer;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


/**
 * <p></p>
 *
 * @author GaoShuangWen
 * @since 2019-11-08 23:14
 */
@Data
@Slf4j
public class ImLoadBalance {

    private CuratorFramework client = null;

    private static String mangerPath = "/im/instance";

    private FastJsonSerializer serializer = FastJsonSerializer.getInstance();

    public ImLoadBalance() {
    }

    public ImLoadBalance(String mangerPath) {
        this.client = ZookeeperClientFactory.getInstance().getZkCli();
       // this.mangerPath = mangerPath;
    }

    public static final ImLoadBalance INSTANCE =
            new ImLoadBalance(mangerPath);

    /**
     * 获取负载最小的IM节点
     *
     * @return
     */
    public ImServerInstance getBestWorker() {
        List<ImServerInstance> workers = getWorkers();
        return balance(workers);
    }

    /**
     * 按照负载排序
     *
     * @param items 所有的节点
     * @return 负载最小的IM节点
     */
    protected ImServerInstance balance(List<ImServerInstance> items) {

        if (items.size() > 0) {
            // 根据balance值从小到大排序
            Collections.sort(items);
            // 返回balance值最小的那个
            return items.get(0);
        } else {
            return null;
        }
    }

    /**
     * 从ZooKeeper中拿到所有IM节点
     */
    protected List<ImServerInstance> getWorkers() {
        List<ImServerInstance> workers = new ArrayList<>();
        List<String> children = null;
        try {
            children = client.getChildren().forPath(mangerPath);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        children.forEach(child -> {
            log.info("child:", child);
            byte[] payload = null;
            try {
                payload = client.getData().forPath(mangerPath + "/" + child);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (null != payload) {
                ImServerInstance worker = serializer.deserialize(payload,
                        ImServerInstance.class);
                workers.add(worker);
            }
        });

        return workers;
    }


}

